home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / gnu / gnu_oleo_1_2_2.lha / oleo-1.2.2 / display.c < prev    next >
C/C++ Source or Header  |  1993-03-03  |  10KB  |  413 lines

  1. /*    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17.  
  18. #include <stdio.h>
  19. #include "display.h"
  20. #include "lists.h"
  21. #include "cell.h"
  22. #include "io-utils.h"
  23.  
  24. #if __STDC__
  25. struct cell_display *
  26. cell_display_of (struct display *disp, CELLREF r, CELLREF c)
  27. #else
  28. struct cell_display *
  29. cell_display_of (disp, r, c)
  30.      struct display *disp;
  31.      CELLREF r;
  32.      CELLREF c;
  33. #endif
  34. {
  35.   int cols = disp->range.hc - disp->range.lc + 1;
  36.   r -= disp->range.lr;
  37.   c -= disp->range.lc;
  38.   return disp->cells + r * cols + c;
  39. }
  40.  
  41.  
  42. void 
  43. free_display (disp)
  44.      struct display *disp;
  45. {
  46.   int rows = disp->range.hr - disp->range.lr + 1;
  47.   int cols = disp->range.hc - disp->range.lc + 1;
  48.   struct cell_display *cd = disp->cells;
  49.   int x, y;
  50.   for (y = 0; y < rows; ++y)
  51.     for (x = 0; x < cols; ++x)
  52.       {
  53.     if (cd->unclipped)
  54.       free (cd->unclipped);
  55.     if (cd->clipped)
  56.       free (cd->clipped);
  57.       }
  58.   free (disp->widths);
  59.   free (disp->heights);
  60.   free (disp->cells);
  61.   free (disp->rowy);
  62.   free (disp->colx);
  63. }
  64.  
  65. void 
  66. damage (disp, cd)
  67.      struct display *disp;
  68.      struct cell_display *cd;
  69. {
  70.   if (cd && !cd->next_damaged)
  71.     {
  72.       cd->next_damaged = disp->damaged;
  73.       disp->damaged = cd;
  74.     }
  75. }
  76.  
  77. #if __STDC__
  78. int
  79. pr_display_cell (struct display *disp, CELLREF r, CELLREF c, CELL *cp)
  80. #else
  81. int
  82. pr_display_cell (disp, r, c, cp)
  83.      struct display *disp;
  84.      CELLREF r;
  85.      CELLREF c;
  86.      CELL *cp;
  87. #endif
  88. {
  89.   int cols = disp->range.hc - disp->range.lc + 1;
  90.   struct cell_display *cd =
  91.   &disp->cells[cols * (r - disp->range.lr) + (c - disp->range.lc)];
  92.   xx_IntRectangle ir = &cd->layout;
  93.   struct font_memo * new_font = 0;
  94.   char * new_unclipped = 0;
  95.   int new_type = 0;
  96.   int new_jst = 0;
  97.  
  98.   if (cp && disp->widths[c - disp->range.lc]
  99.       && disp->heights[r - disp->range.lr])
  100.     {
  101.       new_unclipped = print_cell (cp);
  102.       if (!new_unclipped || *new_unclipped == '\0')
  103.     new_unclipped = 0;
  104.       else
  105.     {
  106.       new_type = GET_TYP (cp);
  107.       new_jst = GET_JST (cp);
  108.       new_font = cp->cell_font;
  109.       if (new_jst == JST_DEF)
  110.         new_jst = default_jst;
  111.     }
  112.     }
  113.  
  114.  
  115.   if (((!new_unclipped && !cd->unclipped)
  116.        || ((new_unclipped && cd->unclipped)
  117.        && !strcmp(cd->unclipped, new_unclipped))) 
  118.       && (cd->font == new_font)
  119.       && (cd->cell_type == new_type)
  120.       && (cd->justification == new_jst))
  121.     return 0;
  122.            
  123.   record_display_damage (disp, xx_IRx (ir), xx_IRy (ir),
  124.              xx_IRw (ir), xx_IRh (ir));
  125.   if (cd->unclipped)
  126.     {
  127.       free (cd->unclipped);
  128.       cd->unclipped = 0;
  129.     }
  130.   if (cd->clipped)
  131.     {
  132.       free (cd->clipped);
  133.       cd->clipped = 0;
  134.     }
  135.   cd->font = new_font;
  136.   cd->cell_type = new_type;
  137.   cd->justification = new_jst;
  138.   if (!cp || !GET_TYP (cp))
  139.     {
  140.       xx_IRinit (&cd->goal, 0, 0, 0, 0);
  141.       xx_IRinit (&cd->clip, 0, 0, 0, 0);
  142.       cd->unclipped = 0;
  143.       return 1;
  144.     }
  145.   cd->unclipped = ck_savestr (new_unclipped);
  146.   cd->clipped = 0;
  147.   disp->metric (cd, disp);
  148.   if (new_type == TYP_INT)
  149.     cd->numeric.integer = cp->c_z.c_l;
  150.   else if (new_type == TYP_FLT)
  151.     cd->numeric.dbl = cp->c_z.c_d;
  152.   else
  153.     {
  154.       cd->clipped = ck_savestr (cd->unclipped);
  155.       cd->clip = cd->goal;
  156.     }
  157.   return 1;
  158. }
  159.  
  160. static void null_metric (cd, disp)
  161.      struct cell_display * cd;
  162.      struct display * disp;
  163. {}
  164.  
  165. static void 
  166. _build_display (disp, range, metric, vdata, scalep)
  167.      struct display *disp;
  168.      struct rng *range;
  169.      cell_display_metric metric;
  170.      void *vdata;
  171.      int scalep;
  172. {
  173.   /* This would be more useful if it handled scrolling. */
  174.   int r, c;
  175.   int rows = range->hr - range->lr + 1;
  176.   int cols = range->hc - range->lc + 1;
  177.   int x, y;
  178.   disp->range = *range;
  179.   disp->widths = (int *) ck_malloc (sizeof (int) * cols);
  180.   disp->heights = (int *) ck_malloc (sizeof (int) * rows);
  181.   disp->rowy = (int *) ck_malloc (sizeof (int) * rows);
  182.   disp->colx = (int *) ck_malloc (sizeof (int) * cols);
  183.   disp->metric = metric ? metric : null_metric;
  184.   disp->vdata = vdata;
  185.   disp->cells = ((struct cell_display *)
  186.          ck_calloc (sizeof (struct cell_display) * rows * cols));
  187.   disp->damaged = (struct cell_display *) disp;
  188.   for (x = 0, r = range->lr; r <= range->hr; ++r)
  189.     {
  190.       disp->rowy[r - range->lr] = x;
  191.       x += disp->heights[r - range->lr] = (scalep ? get_scaled_height : get_height) (r);
  192.     }
  193.   for (y = 0, c = range->lc; c <= range->hc; ++c)
  194.     {
  195.       disp->colx[c - range->lc] = y;
  196.       y += disp->widths[c - range->lc] = (scalep ? get_scaled_width : get_width) (c);
  197.       for (r = range->lr; r <= range->hr; ++r)
  198.     {
  199.       struct cell_display *cd = cell_display_of (disp, r, c);
  200.       cd->r = r;
  201.       cd->c = c;
  202.       pr_display_cell (disp, r, c, find_cell (r, c));
  203.     }
  204.     }
  205. }
  206.  
  207. void 
  208. build_display (disp, range, metric, vdata)
  209.      struct display *disp;
  210.      struct rng *range;
  211.      cell_display_metric metric;
  212.      void *vdata;
  213. {
  214.   _build_display (disp, range, metric, vdata, 1);
  215. }
  216.  
  217. void 
  218. build_unscaled_display (disp, range, metric, vdata)
  219.      struct display *disp;
  220.      struct rng *range;
  221.      cell_display_metric metric;
  222.      void *vdata;
  223. {
  224.   _build_display (disp, range, metric, vdata, 0);
  225. }
  226.  
  227. void 
  228. display_range (rng, disp, x, y, w, h)
  229.      struct rng *rng;
  230.      struct display *disp;
  231.      int x, y, w, h;
  232. {
  233.   int t;
  234.   struct rng *winrng = &disp->range;
  235.   int *rowy = disp->rowy;
  236.   int *heights = disp->heights;
  237.   int *colx = disp->colx;
  238.   int *widths = disp->widths;
  239.   int rows = winrng->hr - winrng->lr + 1;
  240.   int cols = winrng->hc - winrng->lc + 1;
  241.  
  242.   for (t = 0; t < rows - 1; ++t)
  243.     if (rowy[t] + heights[t] - 1 >= y)
  244.       break;
  245.   rng->lr = t + winrng->lr;
  246.  
  247.   while (t < rows - 1)
  248.     {
  249.       if (rowy[t] + heights[t] >= y + h)
  250.     break;
  251.       t++;
  252.     }
  253.   rng->hr = t + winrng->lr;
  254.  
  255.   for (t = 0; t < cols - 1; ++t)
  256.     if (colx[t] + widths[t] - 1 >= x)
  257.       break;
  258.   rng->lc = t + winrng->lc;
  259.  
  260.   while (t < cols - 1)
  261.     {
  262.       if (colx[t] + widths[t] >= x + w)
  263.     break;
  264.       t++;
  265.     }
  266.   rng->hc = t + winrng->lc;
  267. }
  268.  
  269. extern void 
  270. record_display_damage (disp, x, y, w, h)
  271.      struct display *disp;
  272.      int x, y, w, h;
  273. {
  274.   CELLREF r, c;
  275.   struct rng rng;
  276.   display_range (&rng, disp, x, y, w, h);
  277.   for (r = rng.lr; r <= rng.hr && r > 0; ++r)
  278.     for (c = rng.lc; c <= rng.hc && c > 0; ++c)
  279.       damage (disp, cell_display_of (disp, r, c));
  280. }
  281.  
  282.  
  283. void 
  284. layout (disp)
  285.      struct display *disp;
  286. {
  287.   int *widths = disp->widths;
  288.   int *heights = disp->heights;
  289.   int *rowy = disp->rowy;
  290.   int *colx = disp->colx;
  291.   int rows = disp->range.hr - disp->range.lr + 1;
  292.   int cols = disp->range.hc - disp->range.lc + 1;
  293.   int ri, ci;
  294.   struct cell_display *cd;
  295.  
  296.   /* This assigns each non-empty cell's space to itself.  The rest of the */
  297.   /* function allocates the space held by empty cells. */
  298.   for (cd = disp->cells, ri = 0; ri < rows; ++ri)
  299.     for (ci = 0; ci < cols; ++ci, ++cd)
  300.       {
  301.     cd->was_used_by = cd->used_by;
  302.     cd->used_by = cd->unclipped ? cd : 0;
  303.       }
  304.  
  305.   for (ri = 0; ri < rows; ++ri)
  306.     for (ci = 0; ci < cols; ++ci)
  307.       {
  308.     struct cell_display *cd =
  309.     cell_display_of (disp, ri + disp->range.lr, ci + disp->range.lc);
  310.     if (cd->unclipped)
  311.       {
  312.         xx_IntRectangle gr = &cd->goal;
  313.         int xl = xx_IRxl (gr);
  314.         int xh = xx_IRxh (gr);
  315.         int yl = xx_IRyl (gr);
  316.         int rl_answer, rh_answer, cl_answer, ch_answer;
  317.         int rl, rh, cl, ch;
  318.         int rit, cit;
  319.         int xt, yt;
  320.  
  321.         for (cl = ci, xt = colx[cl];
  322.          cl && (xt > xl);
  323.          --cl, xt = colx[cl]);
  324.         for (rl = ri, yt = rowy[rl];
  325.          rl && (yt > yl);
  326.          --rl, yt = rowy[rl]);
  327.         for (ch = ci, xt = colx[ch] + widths[ch];
  328.          (ch < (cols - 1)) && (xt < xh);
  329.          ++ch, xt = colx[ch] + widths[ch]);
  330.         rh = ri;
  331.         /* rl/h & cl/h bound the cells covered by the goal rectangle.
  332.          * Of these, at least ri, ci is unused.  The goal here is to
  333.          * allocate additional cells for use by ri,ci.
  334.          */
  335.         for (rit = ri - 1; rit >= rl; --rit)
  336.           for (cit = cl; ci <= ch; ++cit)
  337.         {
  338.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  339.           if (cdt->used_by)
  340.             goto got_rl;
  341.         }
  342.       got_rl:
  343.         ++rit;
  344.         rl_answer = rit;
  345.  
  346.         for (rit = ri + 1; rit <= rh; ++rit)
  347.           for (cit = cl; ci <= ch; ++cit)
  348.         {
  349.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  350.           if (cdt->used_by)
  351.             goto got_rh;
  352.         }
  353.       got_rh:
  354.         --rit;
  355.         rh_answer = rit;
  356.  
  357.         for (cit = ci - 1; cit >= cl; --cit)
  358.           for (rit = rl_answer; rit <= rh_answer; ++rit)
  359.         {
  360.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  361.           if (cdt->used_by)
  362.             goto got_cl;
  363.         }
  364.       got_cl:
  365.         ++cit;
  366.         cl_answer = cit;
  367.  
  368.         for (cit = ci + 1; cit <= ch; ++cit)
  369.           for (rit = rl_answer; rit <= rh_answer; ++rit)
  370.         {
  371.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  372.           if (cdt->used_by)
  373.             goto got_ch;
  374.         }
  375.       got_ch:
  376.         --cit;
  377.         ch_answer = cit;
  378.  
  379.         for (rit = rl_answer; rit <= rh_answer; ++rit)
  380.           for (cit = cl_answer; cit <= ch_answer; ++cit)
  381.         {
  382.           struct cell_display *cdt = disp->cells + (rit * cols) + cit;
  383.           cdt->used_by = cd;
  384.           if (cdt->was_used_by != cdt->used_by)
  385.             {
  386.               damage (disp, cdt);
  387.               damage (disp, cdt->was_used_by);
  388.             }
  389.         }
  390.  
  391.         xx_IRinit (&cd->layout,
  392.                colx[cl_answer], rowy[rl_answer],
  393.                colx[ch_answer] + widths[ch_answer] - colx[cl_answer],
  394.                rowy[rh_answer] + heights[rh_answer] - rowy[rl_answer]);
  395.       }
  396.       }
  397.  
  398.   /* Unused cells are given to themselves. */
  399.   for (cd = disp->cells, ri = 0; ri < rows; ++ri)
  400.     for (ci = 0; ci < cols; ++ci, ++cd)
  401.       if (!cd->used_by)
  402.     {
  403.       cd->used_by = cd;
  404.       if (cd->was_used_by != cd)
  405.         {
  406.           damage (disp, cd);
  407.           damage (disp, cd->was_used_by);
  408.         }
  409.       xx_IRinit (&cd->layout, colx[ci], rowy[ri],
  410.              widths[ci], heights[ri]);
  411.     }
  412. }
  413.